/**
 * @file hccp_common.h
 * @brief This module provides common structure about sockets and rdma for HCCL
 * @version Copyright (c) Huawei Technologies Co., Ltd. 2019-2025. All rights reserved.
 * @author
 * @date 2019-03-25
 * @defgroup libsocket socket interface
 * @defgroup librdma rdma interface
 * @defgroup libinit init interface
 */

#ifndef __HCCP_COMMON_H__
#define __HCCP_COMMON_H__
#include <stdint.h>
#include <stdbool.h>
#include <arpa/inet.h>
#include <infiniband/verbs.h>

#ifdef __cplusplus
extern "C" {
#endif


#define HCCP_ATTRI_VISI_DEF __attribute__ ((visibility ("default")))

/**
 * @ingroup libsocket
 * implication of tag : tag is used for HCCL identification group information\n
 * macro : size of tag
 */
#define SOCK_CONN_TAG_SIZE 192
#define MAX_INTERFACE_NUM   8
#define MAX_INTERFACE_NAME_LEN   256
#define RA_QOS_ATTR_RESERVED 6
// 临时方案讲网卡数目提升到1024
#define MAX_INTERFACE_NUM_BAK   1024
#define MAX_SOCKET_EVENT_NUM 1024

enum NotifyTypeT {
    NO_USE = 0,
    NOTIFY = 1,
    EVENTID = 2,
};

/**
 * @ingroup libinit
 * white list switch
 */
enum WhiteListStatus {
    WHITE_LIST_DISABLE = 0, /**< enable white list */
    WHITE_LIST_ENABLE, /**< disable white list */
};

/**
 * @ingroup librdma
 */
#define QP_CREATE_WITH_ATTR_VERSION 1
#define RA_QP_CREATE_WITH_ATTR_RESERVED 32
#define CQE_ERR_INFO_MAX_NUM 128
#define HCCP_GID_RAW_LEN 16U
#define REMAP_MR_MAX_NUM 128U

/**
 * @ingroup libcommon
 * others module error code conversion
 */
#define OTHERS_EAGAIN    128301   /* EAGAIN:try again */
#define OTHERS_ENOTSUPP  528302   /* ENOTSUPP: operation not supported */

/**
 * @ingroup libsocket
 * socket module error code conversion
 */
#define SOCK_EAGAIN    128201   /* EAGAIN:no data received by socket */
#define SOCK_CLOSE   128203 /* EINVAL:device异常关闭时作为心跳返回值返回给hccl*/
#define SOCK_ENOENT    228200   /* ENOENT:SOCK_ENOENT means mr async not success right now,revoke the funcion again */
#define SOCK_EADDRINUSE    128205   /* EADDRINUSE：check if IP has been listened when SOCK_EADDRINUSE is returned */
#define SOCK_EADDRNOTAVAIL 128206   /* EADDRNOTAVAIL：check if IP exist when SOCK_EADDRNOTAVAIL is returned */
#define SOCK_ESOCKCLOSED   128207   /* ESOCKCLOSED：socket has been closed */
#define SOCK_ENODEV   228202 /* socket 设备不存在 */

/**
 * @ingroup libinit
 * init module error code conversion
 */
#define HCCP_EAGAIN        128001   /* EAGAIN:try again */
#define HCCP_EINVALIDIPS   328008   /* ranktable中ip和物理网卡的ip不一致 */
#define HCCP_ELINKDOWN     328004   /* 网口down */

/**
 * @ingroup librdma
 * rdma module error code conversion
 */
#define ROCE_EAGAIN    128101   /* EAGAIN:try again */
#define ROCE_ENOMEM    328100   /* ENOMEM: roce module has ENOMEM error */
#define ROCE_EOPENSRC  528101   /* EOPENSRC: open source verbs error */
#define ROCE_ENOENT    228100   /* ENOENT: means mr async not success right now, revoke the funcion again */

/**
 * @ingroup libinit
 * hccp operating environment
 */
enum NetworkMode {
    NETWORK_PEER_ONLINE = 0, /**< Third-party online mode */
    NETWORK_OFFLINE, /**< offline mode */
    NETWORK_ONLINE, /**< online mode */
};

/**
 * @ingroup libinit
 * hccp support protocol type
 */
enum ProtocolTypeT {
    PROTOCOL_RDMA = 0,
    PROTOCOL_UNSUPPORT,
};

/**
 * @ingroup libinit
 * rdma gid, aka infiniband ibv_gid
 */
union HccpGid {
    uint8_t raw[HCCP_GID_RAW_LEN];
    struct {
        uint64_t subnetPrefix;
        uint64_t interfaceId;
    } global;
};

/**
 * @ingroup libinit
 * info need of rdma_agent
 */
struct RaInfo {
    int mode; /**< reference to network_mode */
    unsigned int phyId; /**< physical device id */
};

enum HccnCfgKey {
    HCCN_CFG_UDP_PORT_MODE = 0,
    HCCN_CFG_MULTI_QP_COUNT = 1,
    HCCN_CFG_MULTI_QP_UDP_PORTS = 2,
    HCCN_CFG_KEY_INVALID
};

/**
 * @ingroup libinit
 * ip address
 */
union HccpIpAddr {
    struct in_addr addr;
    struct in6_addr addr6;
};

/**
 * @ingroup libinit
 * hccp init info
 */
struct rdev {
    unsigned int phyId; /**< physical device id */
    int family; /**< AF_INET(ipv4) or AF_INET6(ipv6) */
    union HccpIpAddr localIp;
};

struct RdevInitInfo {
    int mode;
    unsigned int notifyType;
    bool enabled910aLite; /**< true will enable 910A lite, invalid if enabled_2mb_lite is false; default is false */
    bool disabledLiteThread; /**< true will not start lite thread, flag invalid if enabled_910a/2mb_lite is false */
    bool enabled2mbLite; /**< true will enable 2MB lite(include 910A & 910B), default is false */
};

struct SocketInitInfoT {
    struct rdev rdevInfo;
    int scopeId;
};

/**
 * @ingroup libsocket
 * socket listen status
 */
enum ListenPhase {
    LISTEN_OK = 0, /**< socket listen ok */
    LISTEN_CREATE_FD_ERR = 1, /**< socket create fd error */
    LISTEN_BIND_ERR = 2, /**< socket bind socket port error */
    LISTEN_BEGIN_ERR = 3, /**< socket listen error */
};

/**
 * @ingroup libsocket
 * struct of the listen info
 */
struct SocketListenInfoT {
    void *socketHandle; /**< socket handle */
    unsigned int port; /**< Socket listening port number */
    unsigned int phase; /**< refer to enum listen_phase */
    unsigned int err; /**< errno */
};

/**
 * @ingroup libsocket
 * struct of the client socket
 */
struct SocketConnectInfoT {
    void *socketHandle; /**< socket handle */
    union HccpIpAddr remoteIp; /**< IP address of remote socket, [0-7] is reserved for vnic */
    unsigned int port; /**< Socket listening port number */
    char tag[SOCK_CONN_TAG_SIZE]; /**< tag must ended by '\0' */
};

/**
 * @ingroup libsocket
 * struct of the socket to be closed
 */
struct SocketCloseInfoT {
    void *socketHandle; /**< socket handle */
    void *fdHandle; /**< fd handle */
    int disuseLinger; /**< 0:use(default l_linger is RS_CLOSE_TIMEOUT), others:disuse */
};

/**
 * @ingroup libsocket
 * Details about socket after socket is linked
 */
struct SocketInfoT {
    void *socketHandle; /**< socket handle */
    void *fdHandle; /**< fd handle */
    union HccpIpAddr remoteIp; /**< IP address of remote socket */
    int status; /**< socket status:0 not connected 1:connected 2:connect timeout 3:connecting */
    char tag[SOCK_CONN_TAG_SIZE]; /**< tag must ended by '\0' */
};

/**
 * @ingroup libsocket
 * struct of socket event info
 */
#ifdef __x86_64__
#define EPOLL_PACKED __attribute__((packed))
#else
#define EPOLL_PACKED
#endif

struct SocketEventInfoT {
    uint32_t event;
    union {
        void *fdHandle;
        uint64_t u64;
    };
} EPOLL_PACKED;
/**
 * @ingroup libinit
 * Configuration of rdma_agent initializatioin
 */
struct RaInitConfig {
    unsigned int phyId; /**< physical device id */
    unsigned int nicPosition; /**< reference to network_mode */
    int hdcType; /**< reference to drvHdcServiceType */
    bool enableHdcAsync; /**< true will init an extra HDC session for async APIs */
};

struct RaGetIfattr {
    unsigned int phyId; /**< physical device id */
    unsigned int nicPosition; /**< reference to network_mode */
    bool isAll; /**< valid when nic_position is NETWORK_OFFLINE. false: get specific rnic ip, true: get all rnic ip */
};

/**
 * @ingroup libinit
 * id type to get vnic ip
 */
enum IdType {
    PHY_ID_VNIC_IP,
    SDID_VNIC_IP
};

/**
 * @ingroup libinit
 * struct of ip info
 */
struct IpInfo {
    int family;
    union HccpIpAddr ip;
    uint32_t resv[2U];
};

/**
 * @ingroup librdma
 * Flag of RMDA operations
 */
enum RaSendFlags {
    RA_SEND_FENCE = 1 << 0, /**< RDMA operation with fence */
    RA_SEND_SIGNALED = 1 << 1, /**< RDMA operation with signaled */
    RA_SEND_SOLICITED = 1 << 2, /**< RDMA operation with solicited */
    RA_SEND_INLINE = 1 << 3, /**< RDMA operation with inline */
};

/**
 * @ingroup librdma
 * Scatter and gather element
 */
struct SgList {
    uint64_t addr; /**< address of buf */
    uint32_t len; /**< len of buf */
    uint32_t lkey; /**< local addr access key */
};

enum RaWrOpcode {
    RA_WR_RDMA_WRITE,
    RA_WR_RDMA_WRITE_WITH_IMM,
    RA_WR_SEND,
    RA_WR_SEND_WITH_IMM,
    RA_WR_RDMA_READ,
    RA_WR_RDMA_ATOMIC_WRITE = 0xf0,
    RA_WR_RDMA_WRITE_WITH_NOTIFY = 0xf2,
    RA_WR_RDMA_REDUCE_WRITE = 0xf5,
    RA_WR_RDMA_REDUCE_WRITE_WITH_NOTIFY = 0xf6,
};

/**
 * @ingroup librdma
 * port status
 */
enum PortStatus {
    PORT_STATUS_DOWN = 0,
    PORT_STATUS_ACTIVE = 1,
};

/**
 * @ingroup librdma
 * RDMA work request
 */
struct SendWr {
    struct SgList *bufList; /**< list of sg */
    uint16_t bufNum; /**< num of buf_list */
    uint64_t dstAddr; /**< destination address */
    uint32_t rkey;     /**< remote address access key */
    uint32_t op; /**< operations of RDMA supported:RDMA_WRITE:0 */
    int sendFlag; /**< reference to ra_send_flags */
};

struct WrAuxInfo {
    uint8_t dataType;
    uint8_t reduceType;
    uint32_t notifyOffset;
};

struct WrExtInfo {
    uint32_t immData;
    uint16_t resv;
};

struct SendWrlistData {
    unsigned long long dstAddr; /**< destination address */
    unsigned int op; /**< operations of RDMA supported:RDMA_WRITE:0, RDMA_READ:4 */
    int sendFlags; /**< reference to ra_send_flags */
    struct SgList memList; /**< list of sg */
};

struct SendWrlistDataExt {
    unsigned long long dstAddr; /**< destination address */
    unsigned int op; /**< operations of RDMA supported:RDMA_WRITE:0, RDMA_READ:4 */
    int sendFlags; /**< reference to ra_send_flags */
    struct SgList memList; /**< list of sg */
    union {
        struct WrAuxInfo aux; /**< aux info */
        struct WrExtInfo ext; /**< ext info */
    };
};

struct SendWrV2 {
    uint64_t wrId; /**< user assigned work request ID */
    struct SgList *bufList; /**< list of sg */
    uint16_t bufNum; /**< num of buf_list */
    uint64_t dstAddr; /**< destination address */
    uint32_t rkey;     /**< remote address access key */
    uint32_t op; /**< operations of RDMA supported:RDMA_WRITE:0 */
    int sendFlag; /**< reference to ra_send_flags */
    union {
        struct WrAuxInfo aux; /**< aux info */
        struct WrExtInfo ext; /**< ext info */
    };
};

struct WrInfo {
    int sendFlags;                 /**< reference to ra_send_flags */
    uint32_t rkey;                  /**< remote address access key */
    uint32_t op;                    /**< operations of RDMA supported:ra_wr_opcode */
    uint32_t immData;              /**< imm data */
    uint64_t wrId;                 /**< user assigned work request ID */
    uint64_t dstAddr;              /**< destination address */
    struct SgList memList;        /**< sg info */
    struct WrAuxInfo aux;         /**< aux info */
};

struct RecvWrlistData {
    uint64_t wrId; /**< user assigned work request ID */
    struct SgList memList; /**< list of sg */
};

/**
 * @ingroup libsocket
 * Socket whitelist
 */
struct SocketWlistInfoT {
    union HccpIpAddr remoteIp; /**< IP address of remote */
    unsigned int connLimit; /**< limit of whilte list */
    char tag[SOCK_CONN_TAG_SIZE]; /**< tag used for whitelist must ended by '\0' */
};

/**
 * @ingroup librdma
 * Flag of mr access
 */
enum RaAccessFlags {
    RA_ACCESS_LOCAL_WRITE  = 1, /**< mr local write access */
    RA_ACCESS_REMOTE_WRITE = (1 << 1), /**< mr remote write access */
    RA_ACCESS_REMOTE_READ  = (1 << 2), /**< mr remote read access */
    RA_ACCESS_REMOTE_ATOMIC = (1 << 3), /**< mr remote atomic access */
    RA_ACCESS_REDUCE       = (1 << 8),
};

#define mem_mr_access_flags ra_access_flags

/**
 * @ingroup librdma
 * wqe template info
 */
struct WqeInfo {
    unsigned int sqIndex; /**< index of sq */
    unsigned int wqeIndex; /**< index of wqe */
};

/**
 * @ingroup librdma
 * doorbell info
 */
struct DbInfo {
    unsigned int dbIndex; /**< index of db */
    unsigned long dbInfo; /**< db content */
};

/**
 * @ingroup librdma
 * respond of sending work request
 */
struct SendWrRsp {
    union {
        struct WqeInfo wqeTmp; /**< wqe template info */
        struct DbInfo db; /**< doorbell info */
    };
};

struct IfaddrInfo {
    union HccpIpAddr ip; /* Address of interface */
    struct in_addr mask; /* Netmask of interface */
};

struct InterfaceInfo {
    int family;
    int scopeId;
    struct IfaddrInfo ifaddr; /* Address and netmask of interface */
    char ifname[MAX_INTERFACE_NAME_LEN]; /* Name of interface */
};

struct MrInfoT {
    void *addr; /**< starting address of mr */
    unsigned long long size; /**< size of mr */
    int access; /**< access of mr, reference to ra_access_flags */
    unsigned int lkey; /**< local addr access key */
    unsigned int rkey; /**< remote addr access key */
};

struct MemRemapInfo {
    void *addr; /**< starting address of needed remap memory */
    unsigned long long size; /**< size of needed remap memory */
};

enum RaWcOpcode {
    RA_WC_SEND,
    RA_WC_RDMA_WRITE,
    RA_WC_RDMA_READ,
    RA_WC_RECV			= 1 << 7,
    RA_WC_RECV_RDMA_WITH_IMM,
};

enum RaEpollEvent {
    RA_EPOLLIN = 0,
    RA_EPOLLOUT,
    RA_EPOLLPRI,
    RA_EPOLLERR,
    RA_EPOLLHUP,
    RA_EPOLLET,
    RA_EPOLLONESHOT,
    RA_EPOLLOUT_LET_ONESHOT,
    RA_EPOLLINVALD
};

struct CqAttr {
    void **qpContext;
    struct ibv_cq **ibSendCq;
    struct ibv_cq **ibRecvCq;
    int sendCqDepth;
    int recvCqDepth;
    int sendCqEventId;
    int recvCqEventId;
    struct ibv_comp_channel *sendChannel;
    struct ibv_comp_channel *recvChannel;
    void *srqContext;
};

struct SrqAttr {
    void **context;
    struct ibv_srq **ibSrq;
    struct ibv_cq **ibRecvCq;
    int cqDepth;
    int srqDepth;
    int maxSge;
    int srqEventId;
};

struct QosAttr {
    unsigned char tc;          // traffic class
    unsigned char sl;          // priority(service level)
    unsigned char reserved[RA_QOS_ATTR_RESERVED];
};

struct CqeErrInfo {
    uint32_t status;
    uint32_t qpn;
    struct timeval time;
};

struct CqExtAttr {
    int sendCqDepth;
    int recvCqDepth;
    int sendCqCompVector;
    int recvCqCompVector;
};

struct AiDataPlaneWq {
    unsigned wqn;
    unsigned long long bufAddr;
    unsigned int wqebbSize;
    unsigned int depth;
    unsigned long long headAddr;
    unsigned long long tailAddr;
    unsigned long long swdbAddr;
    unsigned long long dbReg;
    unsigned int reserved[8U];
};

struct AiDataPlaneCq {
    unsigned int cqn;
    unsigned long long bufAddr;
    unsigned int cqeSize;
    unsigned int depth;
    unsigned long long headAddr;
    unsigned long long tailAddr;
    unsigned long long swdbAddr;
    unsigned long long dbReg;
    unsigned int reserved[2U];
};

struct AiDataPlaneInfo {
    struct AiDataPlaneWq sq;
    struct AiDataPlaneWq rq;
    struct AiDataPlaneCq scq;
    struct AiDataPlaneCq rcq;
    unsigned int reserved[8U];
};

union AiDataPlaneCstmFlag {
    struct {
        uint32_t cqCstm  : 1; // 0: hccp poll cq; 1: caller poll cq
        uint32_t reserved : 31;
    } bs;
    uint32_t value;
};

enum {
    HCCP_RDMA_NOR_MODE      = 0,
    HCCP_RDMA_GDR_TMPL_MODE = 1,
    HCCP_RDMA_OP_MODE       = 2,
    HCCP_RDMA_GDR_ASYN_MODE = 3,
    HCCP_RDMA_OP_MODE_EXT   = 4,
    HCCP_RDMA_ERR_MODE      = 5
};

struct QpExtAttrs {
    int qpMode;
    // cq attr
    struct CqExtAttr cqAttr;
    // qp attr
    struct ibv_qp_init_attr qpAttr;
    // version control and reserved
    int version;
    int memAlign; // 0,1:4KB, 2:2MB
    uint32_t udpSport;
    union AiDataPlaneCstmFlag dataPlaneFlag; // only valid in ra_ai_qp_create
    uint32_t reserved[29U];
};

struct AiQpInfo {
    unsigned long long aiQpAddr; // refer to struct ibv_qp *
    unsigned int sqIndex; // index of sq
    unsigned int dbIndex; // index of db

    // below cq related info valid when data_plane_flag.bs.cq_cstm was 1
    unsigned long long aiScqAddr; // refer to struct ibv_cq *scq
    unsigned long long aiRcqAddr; // refer to struct ibv_cq *rcq
    struct AiDataPlaneInfo dataPlaneInfo;
};

struct TypicalQp {
    uint32_t qpn;
    uint32_t psn;
    uint32_t gidIdx;
    uint8_t resv1[4U]; // for compatibility issue
    uint8_t gid[HCCP_GID_RAW_LEN];
    uint32_t tc;
    uint32_t sl;
    uint32_t retryCnt;
    uint32_t retryTime;
    // version control and reserved
    int version;
    uint32_t reserved[32U];
    uint8_t resv2[4U]; // for compatibility issue
};

struct QpAttr {
    unsigned int qpn;
    unsigned int udpSport;
    unsigned int psn;
    unsigned int gidIdx;
    unsigned char gid[HCCP_GID_RAW_LEN];
};

struct LoopbackQpPair {
    void *ibvQp0;
    void *ibvQp1;
};

struct SocketErrInfo {
    struct timeval time;
    int errNo;
    int action; // refer to enum rs_conn_state
    char resv[32U];
};

struct ServerSocketErrInfo {
    struct SocketErrInfo epollWait;
    struct SocketErrInfo accept;
};

enum SaveSnapshotAction {
    SAVE_SNAPSHOT_ACTION_PRE_PROCESSING = 0,
    SAVE_SNAPSHOT_ACTION_POST_PROCESSING = 1,
    SAVE_SNAPSHOT_ACTION_MAX,
};
#ifdef __cplusplus
}
#endif
#endif
